/**
 * 尤铭瑶遗忘曲线理论： （2023.10.7修改版）
 * R = exp(-t/S)  t单位：分钟
 * S(1) = 1200/(1.1^(1.4^(c)-1)
 * 当某次复习后，t=0，S(i+1) = S(i) * (1 + (E-1)/ln(1+exp(1.5c)) )
 * E = ( (R-0.3)/(2*exp(7.65*(R-0.3))) -1.5R + 2.5 ) * 1.5
 * c: 该单词上次复习时的错误次数
 * R：记忆留存率   留存的记忆占初始记忆的比例
 * S：记忆质量   与遗忘速度有关，S越大，忘的越慢
 * E：复习效果   大小与目前的记忆留存率有关，在大约R=0.22时最大
 * 数字是我结合生活经验瞎掰的，不一定准确，而且人与人的体质不能一概而论
 */

const ForgetLine = 32;

function secondTime() {
    return parseInt(+new Date()/1000);
}

/**
 * return int
 * @param t double
 * @param memQuality double
 */
function calcIntMemKeepIndex(t,memQuality) {
    return Math.trunc(Math.exp((-t/memQuality))*100);
}

function getForgetTime(wordContent) {
    if(wordContent[1] == 0)
        return 0;
    let R = Math.exp(((wordContent[1]-secondTime())/60/wordContent[3]));
    let nowTime =  -wordContent[3]*Math.log(R)/60;
    let forgetFullTime = -wordContent[3]*Math.log(ForgetLine/100)/60;
    let t = forgetFullTime - nowTime;
    return t < 0 ? 0 : t;
}

/**
 * return double
 * @param t
 * @param memQuality
 * @param lastMisCount
 */
function calcNewMemQuality(t,memQuality,lastMisCount) {
    let R = Math.exp((-t/memQuality));
    let misDecline = Math.log(1+Math.exp(Math.pow(1.5,lastMisCount)));
    let reviewEfficiency = (R-0.3)/(2*Math.exp(7.65*(R-0.3)))-1.5*R+2.5;
    reviewEfficiency *= 1.5 //数值修正
    reviewEfficiency = 1+(reviewEfficiency-1)/misDecline;
    return (memQuality*reviewEfficiency);
}

function calcInitialMemQuality(lastMisCount) {
    return 1200/(Math.pow(1.1,Math.pow(1.4,lastMisCount)-1));
}

function getWordList() {
    let lists = Array();
    let a = 0;
    $.ajaxSetup({async:false});
    $.get('/module/user/ManageWordLib.php',function(data){
        lists = JSON.parse(data);
        let word_count = 0;
        let page = -1;
        for (let j = lists.length-1;j>=0;j--) {
            let list = JSON.parse(lists[j]);
            lists[j] = list;
            //console.log(lists[j]);
        }
    });
    $.ajaxSetup({async:true});
    //console.log(a);
    //console.log(lists[0]);
    return lists;
}

function calcIntMemKeepIndexByWordContent(content) {
    return calcIntMemKeepIndex((secondTime()-content[1])/60,content[3])
}

function calcNewMemQualityByWordContent(content, misCount) {
    if (content[1] == 0) {
        return calcInitialMemQuality(misCount);
    } else {
        return calcNewMemQuality((secondTime() -content[1])/60, content[3], misCount);
    }
}

function updateReviewedWords(Words) {
    let lists = getWordList();
    for (let j = lists.length-1;j>=0;j--) {
        let words = Object.keys(lists[j]);
        let contents = Object.values(lists[j]);
        for (let i = 0;i<words.length;i++) {
            for (let w of Words) {
                if(words[i] == w[0] && contents[i][0] == w[1][0]) {
                    let NewMemQuality = calcNewMemQualityByWordContent(w[1],w[1][2]);
                    lists[j][words[i]] = [w[1][0],secondTime(),0,NewMemQuality];
                    console.log(lists[j][words[i]]);
                }
            }
        }
    }
    return pushRemoteUserWordlist(lists);
}


/*
{"\u82f9\u679c":["apple",0,0,1200],"443":["54425",0,0,1200],"1231":["12312",1696779130,0,1200],"eteyt":["hdgh",1696770000,0,1200]}
 {"443":["54425",1697000633,0,1155.1122031874013],"1231":["12312",1697000633,0,2404.665162458818],"\u82f9\u679c":["apple",1697000633,0,1200],"eteyt":["hdgh",1697000633,0,2336.5058204497504]}
 */

function pushRemoteUserWordlist(listdata) {
    let result;
    $.ajaxSetup({async:false});
    $.post("/module/user/ManageWordLib.php",{
        data:JSON.stringify(listdata),
    },function(data){
        result = data;
    });
    $.ajaxSetup({async:true});
    return result;
}


function getWordsLowerBy(byWhat) {
    let lists = getWordList();
    let LowList = new Map();
    for (let j = lists.length-1;j>=0;j--) {
        let words = Object.keys(lists[j]);
        let contents = Object.values(lists[j]);
        for (let i = 0;i<words.length;i++) {
            if(contents[i][1] == 0) {
                LowList.set(words[i],contents[i]);
            } else {
                if(calcIntMemKeepIndexByWordContent(contents[i]) <= byWhat) {
                    LowList.set(words[i],contents[i]);
                }
            }
        }
    }
    return LowList;
}


function generageReviewMap() {
    let savedCount = 0;
    let reviewListMap = new Map();
    let lowMap = getWordsLowerBy(ForgetLine);
    for (let entry of lowMap) {
        if (savedCount < 20) {
            if (entry[1][1] == 0) {
                reviewListMap.set(entry[0], entry[1]);
                savedCount++
            }
        } else {
            break;
        }
    }
    for (let entry of lowMap) {
        if (savedCount < 20) {
            if (entry[1][1] != 0) {
                reviewListMap.set(entry[0], entry[1]);
                savedCount++
            }
        } else {
            break;
        }
    }
    return reviewListMap;
}

function hour2Date(HourTime) {
    const date = new Date((secondTime()+HourTime*3600)*1000);
    const year = date.getFullYear().toString().padStart(4, '0');
    const month = (date.getMonth() + 1).toString().padStart(2, '0');
    const day = date.getDate().toString().padStart(2, '0');
    const hour = date.getHours().toString().padStart(2, '0');
    const minute = date.getMinutes().toString().padStart(2, '0');
    return (`${year}-${month}-${day} ${hour}:${minute}`); // 2023-02-16 08:25:05
}

// for (let entry of getWordsLowerBy(100)) {
//     console.log(entry[0],entry[1]);
//     console.log(calcIntMemKeepIndexByWordContent(entry[1]));
//     console.log(hour2Date(getForgetTime(entry[1])));
// }

